/* ----------------------------------------------------------------------------
 * Copyright (c) Huawei Technologies Co., Ltd. 2013-2019. All rights reserved.
 * Description: LiteOS Task Module Implementation
 * Author: liulei
 * Create: 2013-01-01
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 * 1. Redistributions of source code must retain the above copyright notice, this list of
 * conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice, this list
 * of conditions and the following disclaimer in the documentation and/or other materials
 * provided with the distribution.
 * 3. Neither the name of the copyright holder nor the names of its contributors may be used
 * to endorse or promote products derived from this software without specific prior written
 * permission.
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * --------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------------
 * Notice of Export Control Law
 * ===============================================
 * Huawei LiteOS may be subject to applicable export control laws and regulations, which might
 * include those applicable to Huawei LiteOS of U.S. and the country in which you are located.
 * Import, export and usage of Huawei LiteOS in any manner by you shall be in compliance with such
 * applicable export control laws and regulations.
 * --------------------------------------------------------------------------- */

#include "los_task_pri.h"
#include "los_base_pri.h"
#include "los_memory_pri.h"
#include "los_priqueue_pri.h"
#include "los_sem_pri.h"
#include "los_mux_pri.h"
#include "los_mux_debug_pri.h"
#include "los_hw_pri.h"
#include "los_exc.h"
#include "los_memstat_pri.h"
#ifdef LOSCFG_KERNEL_RUNSTOP
#include "los_runstop.ph"
#endif
#ifdef LOSCFG_KERNEL_TICKLESS
#include "los_tickless_pri.h"
#endif
#ifdef LOSCFG_KERNEL_CPUP
#include "los_cpup_pri.h"
#endif
#if (LOSCFG_BASE_CORE_SWTMR == YES)
#include "los_swtmr_pri.h"
#endif
#ifdef LOSCFG_LIB_LIBC
#include "string.h"
#endif
#ifdef LOSCFG_TASK_STACK_PROTECT
#include "hisoc/mmu_config.h"
extern SENCOND_PAGE stAppPage;
#endif

#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */

LITE_OS_SEC_BSS LosTask g_losTask;

LITE_OS_SEC_BSS LosTaskCB *g_taskCBArray;
LITE_OS_SEC_BSS size_t g_losTaskLock;
LITE_OS_SEC_BSS UINT32 g_taskMaxNum;
LITE_OS_SEC_BSS UINT32 g_idleTaskID;
LITE_OS_SEC_BSS UINT32 g_swtmrTaskID;
LITE_OS_SEC_DATA_INIT LOS_DL_LIST g_losFreeTask;
LITE_OS_SEC_DATA_INIT LOS_DL_LIST g_taskRecyleList;
LITE_OS_SEC_BSS SortLinkAttribute g_taskSortLink;
LITE_OS_SEC_BSS BOOL g_taskScheduled;

#if (LOSCFG_BASE_CORE_TSK_MONITOR == YES)
TSKSWITCHHOOK g_taskSwitchHook = (TSKSWITCHHOOK)NULL; /*lint !e611*/
TSKSWITCHHOOK g_pfnUsrTskSwitchHook = (TSKSWITCHHOOK)NULL; /*lint !e611*/
#endif /* LOSCFG_BASE_CORE_TSK_MONITOR == YES */

#if (OS_PERF_TSK_FILTER == YES)
TSKSWITCHHOOK g_perfTskFilterHook = NULL;
#endif

static VOID osConsoleIDSetHook(UINT32 param1,
                               UINT32 param2) __attribute__((weakref("osSetConsoleID"))); /*lint -e402*/
static VOID OsExcStackCheckHook(VOID)__attribute__((weakref("OsExcStackCheck"))); /*lint -e402*/

#define OS_CHECK_TASK_BLOCK ((OS_TASK_STATUS_DELAY | OS_TASK_STATUS_PEND | OS_TASK_STATUS_SUSPEND | OS_TASK_STATUS_EVENT | OS_TASK_STATUS_PEND_QUEUE))
#define OS_TASK_ID_CHECK(taskID) LOS_ASSERT_COND(OS_TSK_GET_INDEX(taskID) < g_taskMaxNum)
#define OS_CHECK_TSK_PID_NOIDLE(taskID) (OS_TSK_GET_INDEX(taskID) >= g_taskMaxNum)

#ifdef LOSCFG_EXC_INTERACTION
extern UINT32 osExcInteractionTaskCheck(TSK_INIT_PARAM_S *initParam);
#endif
/*****************************************************************************
 Function : osTskIdleBGD
 Description : Idle background.
 Input       : None
 Output      : None
 Return      : None
 *****************************************************************************/
LITE_OS_SEC_TEXT VOID OsIdleTask(VOID)
{
    while (1) {
#ifdef LOSCFG_KERNEL_RUNSTOP
        if (TRUE == g_bSysdoneFlag) {
            osSystemSuspend();
        }
#endif

#ifdef LOSCFG_KERNEL_TICKLESS
        if (OsTickIrqFlagGet()) {
            OsTickIrqFlagSet(0);
            OsTicklessStart(LOSCFG_BASE_CORE_TICK_PER_SECOND);
        }

#endif
        wfi();
    }
}

/*****************************************************************************
 Function : OsTaskPriModify
 Description : Change task priority.
 Input       : taskCB    --- task control block
                 priority      --- priority
 Output      : None
 Return      : None
 *****************************************************************************/
LITE_OS_SEC_TEXT_MINOR VOID OsTaskPriModify(LosTaskCB *taskCB, UINT16 priority)
{
    if (taskCB->taskStatus & OS_TASK_STATUS_READY) {
        OsPriqueueDequeue(&taskCB->pendList);
        taskCB->priority = priority;
        OsPriqueueEnqueue(&taskCB->pendList, taskCB->priority);
    } else {
        taskCB->priority = priority;
    }
}

/*****************************************************************************
 Function : OsTaskAdd2TimerList
 Description : Add task to sorted delay list.
 Input       : taskCB    --- task control block
               timeout    --- wait time, ticks
 Output      : None
 Return      : None
 *****************************************************************************/
LITE_OS_SEC_TEXT VOID OsTaskAdd2TimerList(LosTaskCB *taskCB, UINT32 timeout)
{
    SET_SORTLIST_VALUE(&(taskCB->sortList), timeout);
    OsAdd2SortLink(&g_taskSortLink, &taskCB->sortList);
}

LITE_OS_SEC_TEXT VOID OsTimerListDelete(LosTaskCB *taskCB)
{
    OsDeleteSortLink(&g_taskSortLink, &taskCB->sortList);
}

LITE_OS_SEC_TEXT VOID OsTaskScan(VOID)
{
    SortLinkList *sortList = NULL;
    LosTaskCB *taskCB = NULL;
    BOOL needSchedule = FALSE;
    UINT16 tempStatus;
    LOS_DL_LIST *listObject = NULL;

    g_taskSortLink.cursor = (g_taskSortLink.cursor + 1) & OS_TSK_SORTLINK_MASK;
    listObject = g_taskSortLink.sortLink + g_taskSortLink.cursor;

    if (LOS_ListEmpty(listObject)) {
        return;
    }
    sortList = LOS_DL_LIST_ENTRY((listObject)->pstNext, SortLinkList, sortLinkNode);
    UWROLLNUMDEC(sortList->idxRollNum);

    while (UWROLLNUM(sortList->idxRollNum) == 0) {
        LOS_ListDelete(&sortList->sortLinkNode);
        taskCB = LOS_DL_LIST_ENTRY(sortList, LosTaskCB, sortList);
        taskCB->taskStatus &= (~OS_TASK_STATUS_PEND_TIME);
        tempStatus = taskCB->taskStatus;
        if (OS_TASK_STATUS_PEND & tempStatus) {
            taskCB->taskStatus &= ~(OS_TASK_STATUS_PEND);
            taskCB->taskStatus |= OS_TASK_STATUS_TIMEOUT;
            LOS_ListDelete(&taskCB->pendList);
            taskCB->taskSem = NULL;
            taskCB->taskMux = NULL;
        } else if (OS_TASK_STATUS_EVENT & tempStatus) {
            taskCB->taskStatus &= ~(OS_TASK_STATUS_EVENT);
            taskCB->taskStatus |= OS_TASK_STATUS_TIMEOUT;
        } else if (OS_TASK_STATUS_PEND_QUEUE & tempStatus) {
            LOS_ListDelete(&taskCB->pendList);
            taskCB->taskStatus &= ~(OS_TASK_STATUS_PEND_QUEUE);
            taskCB->taskStatus |= OS_TASK_STATUS_TIMEOUT;

        } else {
            taskCB->taskStatus &= ~(OS_TASK_STATUS_DELAY);
        }

        if (!(OS_TASK_STATUS_SUSPEND & tempStatus)) {
            taskCB->taskStatus |= OS_TASK_STATUS_READY;
            OsPriqueueEnqueue(&taskCB->pendList, taskCB->priority);
            needSchedule = TRUE;
        }

        if (LOS_ListEmpty(listObject)) {
            break;
        }

        sortList = LOS_DL_LIST_ENTRY((listObject)->pstNext, SortLinkList, sortLinkNode);
    }

    if (needSchedule != FALSE) {
        LOS_Schedule();
    }
}

/*****************************************************************************
 Function : OsTaskInit
 Description : Task init function.
 Input       : None
 Output      : None
 Return      : LOS_OK on success or error code on failure
 *****************************************************************************/
LITE_OS_SEC_TEXT_INIT UINT32 OsTaskInit(VOID) /*lint -e661 -e662 -e416*/
{
    UINT32 index;
    UINT32 ret;
    UINT32 size;

    g_taskMaxNum = LOSCFG_BASE_CORE_TSK_LIMIT;
    size = (g_taskMaxNum + 1) * sizeof(LosTaskCB);
    g_taskCBArray = (LosTaskCB *)LOS_MemAlloc(m_aucSysMem0, size);
    if (g_taskCBArray == NULL) {
        return LOS_ERRNO_TSK_NO_MEMORY;
    }
    (VOID)memset_s(g_taskCBArray, size, 0, size);

    LOS_ListInit(&g_losFreeTask);
    LOS_ListInit(&g_taskRecyleList);
    for (index = 0; index < g_taskMaxNum; index++) {
        g_taskCBArray[index].taskStatus = OS_TASK_STATUS_UNUSED;
        g_taskCBArray[index].taskID = index;
        LOS_ListTailInsert(&g_losFreeTask, &g_taskCBArray[index].pendList);
    }

    (VOID)memset_s((void *)(&g_losTask), sizeof(LosTask), 0, sizeof(LosTask));
    g_losTask.runTask = &g_taskCBArray[g_taskMaxNum];
    g_losTask.runTask->taskID = index;
    g_losTask.runTask->taskStatus = (OS_TASK_STATUS_UNUSED | OS_TASK_STATUS_RUNNING);
    g_losTask.runTask->priority = OS_TASK_PRIORITY_LOWEST + 1;
    OsPriqueueInit();

    osMuxDlockCheckInitHook();

    ret = OsSortLinkInit(&g_taskSortLink);
    if (ret != LOS_OK) {
        return LOS_ERRNO_TSK_NO_MEMORY;
    }

    return LOS_OK;
} /*lint +e661 +e662 +e416*/

/*****************************************************************************
 Function : OsIdleTaskCreate
 Description : Create idle task.
 Input       : None
 Output      : None
 Return      : LOS_OK on success or error code on failure
 *****************************************************************************/
LITE_OS_SEC_TEXT_INIT UINT32 OsIdleTaskCreate(VOID)
{
    UINT32 ret;
    TSK_INIT_PARAM_S taskInitParam;

    (VOID)memset_s((void *)(&taskInitParam), sizeof(TSK_INIT_PARAM_S), 0, sizeof(TSK_INIT_PARAM_S));
    taskInitParam.pfnTaskEntry = (TSK_ENTRY_FUNC)OsIdleTask;
    taskInitParam.uwStackSize = LOSCFG_BASE_CORE_TSK_IDLE_STACK_SIZE;
    taskInitParam.pcName = "IdleCore000";
    taskInitParam.usTaskPrio = OS_TASK_PRIORITY_LOWEST;
    ret = LOS_TaskCreate(&g_idleTaskID, &taskInitParam);

    return ret;
}

/*****************************************************************************
 Function : LOS_CurTaskIDGet
 Description : get id of current running task.
 Input       : None
 Output      : None
 Return      : task id
 *****************************************************************************/
LITE_OS_SEC_TEXT UINT32 LOS_CurTaskIDGet(VOID)
{
    if (g_losTask.runTask == NULL) {
        return LOS_ERRNO_TSK_ID_INVALID;
    }
    return g_losTask.runTask->taskID;
}

/*****************************************************************************
 Function : OsTaskSelfDelete
 Description : Delete self task
 Input       : taskID --- Task ID, intSave
                 intSave   --- interrupt flag
 Output      : None
 Return      : LOS_OK on success or error code on failure
 *****************************************************************************/
LITE_OS_SEC_TEXT_INIT UINT32 OsTaskSelfDelete(UINT32 taskID, UINTPTR intSave)
{
    LosTaskCB *taskCB = NULL;
    UINT16 tempStatus;

    taskCB = OS_TCB_FROM_TID(taskID);
    tempStatus = taskCB->taskStatus;
    if (OS_TASK_STATUS_READY & tempStatus) {
        OsPriqueueDequeue(&taskCB->pendList);
        taskCB->taskStatus &= (~OS_TASK_STATUS_READY);
    } else if ((OS_TASK_STATUS_PEND | OS_TASK_STATUS_PEND_QUEUE) & tempStatus) {
        LOS_ListDelete(&taskCB->pendList);
        if ((OS_TASK_STATUS_DELAY | OS_TASK_STATUS_PEND_TIME) & tempStatus) {
            OsTimerListDelete(taskCB);
        }
    }

    taskCB->taskStatus &= (~(OS_TASK_STATUS_SUSPEND));
    taskCB->taskStatus |= OS_TASK_STATUS_UNUSED;
    taskCB->event.uwEventID = 0xFFFFFFFF;
    taskCB->eventMask = 0;
#ifdef LOSCFG_KERNEL_CPUP
    (VOID)memset_s((VOID *)&g_cpup[taskCB->taskID], sizeof(OsCpupCB), 0, sizeof(OsCpupCB));
#endif
#ifdef OS_MEM_ENABLE_MEM_STATISTICS
    OS_MEM_CLEAR(taskID);
#endif
    g_losTask.newTask = LOS_DL_LIST_ENTRY(OsPriqueueTop(), LosTaskCB, pendList); /*lint !e413*/
    if (OS_TASK_STATUS_RUNNING & taskCB->taskStatus) {
        LOS_ListTailInsert(&g_taskRecyleList, &taskCB->pendList);
        g_losTask.runTask = &g_taskCBArray[g_taskMaxNum];
        g_losTask.runTask->taskID = taskID;
        g_losTask.runTask->taskStatus = taskCB->taskStatus;
        g_losTask.runTask->topOfStack = taskCB->topOfStack;
        g_losTask.runTask->taskName = taskCB->taskName;
        taskCB->taskStatus = OS_TASK_STATUS_UNUSED;
        (VOID)LOS_IntRestore(intSave);
        OsSchedule();
        return LOS_OK;
    } else if (OS_TASK_STATUS_UNUSED & taskCB->taskStatus) {
        (VOID)LOS_IntRestore(intSave);
        OsSchedule();
        return LOS_OK;
    }

    (VOID)LOS_IntRestore(intSave);
    return LOS_OK;
}

#if (LOSCFG_BASE_CORE_TSK_MONITOR == YES)
LITE_OS_SEC_TEXT static VOID OsTaskStackCheck(VOID)
{
    if ((*(AARCHPTR *)(g_losTask.runTask->topOfStack)) != OS_TASK_MAGIC_WORD) {
        PRINT_ERR("CURRENT task ID: %s:%d stack overflow!\n", g_losTask.runTask->taskName,
                  g_losTask.runTask->taskID);
    }
    if (((AARCHPTR)(g_losTask.newTask->stackPointer) <= g_losTask.newTask->topOfStack) ||
        ((AARCHPTR)(g_losTask.newTask->stackPointer) > g_losTask.newTask->topOfStack +
         g_losTask.newTask->stackSize)) {
        PRINT_ERR("HIGHEST task ID: %s:%d SP error!\n", g_losTask.newTask->taskName, g_losTask.newTask->taskID);
        PRINT_ERR("HIGHEST task StackPointer: %p TopOfStack: %p\n", g_losTask.newTask->stackPointer,
                  g_losTask.newTask->topOfStack);
    }

    if (g_pfnUsrTskSwitchHook != NULL) {
        g_pfnUsrTskSwitchHook();
    }
    if (OsExcStackCheckHook) { /*lint !e506*/
        OsExcStackCheckHook();
    }
}

LITE_OS_SEC_TEXT_MINOR VOID OsTaskMonInit(VOID)
{
    g_taskSwitchHook = OsTaskStackCheck;
    g_pfnUsrTskSwitchHook = (TSKSWITCHHOOK)NULL; /*lint !e611*/
    return;
}
#endif

/*****************************************************************************
 Function : OsTaskSwitchCheck
 Description : Check task switch
 Input       : Node
 Output      : None
 Return      : None
 *****************************************************************************/
LITE_OS_SEC_TEXT_MINOR UINT32 OsTaskSwitchCheck(VOID)
{
#if (LOSCFG_BASE_CORE_TSK_MONITOR == YES)
    if (g_taskSwitchHook != NULL) {
        g_taskSwitchHook();
    }
#endif /* LOSCFG_BASE_CORE_TSK_MONITOR == YES */

#if (OS_PERF_TSK_FILTER == YES)
    if (g_perfTskFilterHook != NULL) {
        g_perfTskFilterHook();
    }
#endif

    osTaskTimeUpdateHook(g_losTask.newTask->taskID, LOS_TickCountGet());

#ifdef LOSCFG_KERNEL_CPUP
    OsTskCycleEndStart();
#endif /* LOSCFG_KERNEL_CPUP */
    return LOS_OK;
}
/*****************************************************************************
 Function : OsTaskEntry
 Description : All task entry
 Input       : taskID     --- The ID of the task to be run
 Output      : None
 Return      : None
 *****************************************************************************/
LITE_OS_SEC_TEXT_INIT VOID OsTaskEntry(UINT32 taskID)
{
    LosTaskCB *taskCB = NULL;
    UINT32 intSave;

    OS_TASK_ID_CHECK(taskID);

    taskCB = OS_TCB_FROM_TID(taskID);
    if (taskCB->threadJoin) {
        taskCB->threadJoinRetval = taskCB->taskEntry(taskCB->args[0],
            taskCB->args[1],
            taskCB->args[2],
            taskCB->args[3]);
    } else {
        taskCB->taskEntry(taskCB->args[0],
            taskCB->args[1],
            taskCB->args[2],
            taskCB->args[3]); /*lint !e534*/
    }

    if (taskCB->taskStatus & LOS_TASK_STATUS_DETACHED) {
        intSave = LOS_IntLock();
        g_losTaskLock = 0;
        (VOID)OsTaskSelfDelete(taskCB->taskID, intSave);
    } else { /* join mode: waiting for child task done */
        intSave = LOS_IntLock();
        g_losTaskLock = 0;

        LOS_TaskLock();
        if (taskCB->threadJoin) {
            if (LOS_SemPost((UINT32)(((LosSemCB *)taskCB->threadJoin)->semID)) != LOS_OK) {
                PRINT_ERR("OsTaskEntry LOS_SemPost fail!\n");
            }
            taskCB->threadJoin = NULL;
        }

        if (OS_TASK_STATUS_READY & taskCB->taskStatus) {
            OsPriqueueDequeue(&taskCB->pendList);
            taskCB->taskStatus &= (~OS_TASK_STATUS_READY);
        }
        LOS_TaskUnlock();
        (VOID)LOS_IntRestore(intSave);
        LOS_Schedule();
    }
}

/*****************************************************************************
 Function : LOS_TaskCreateOnly
 Description : Create a task and suspend
 Input       : initParam --- Task init parameters
 Output      : taskID    --- Save task ID
 Return      : LOS_OK on success or error code on failure
 *****************************************************************************/
LITE_OS_SEC_TEXT_INIT UINT32 LOS_TaskCreateOnly(UINT32 *taskID, TSK_INIT_PARAM_S *initParam)
{
    UINT32 tempTaskID;
    UINTPTR intSave;
    VOID *topStack = NULL;
    VOID *stackPtr = NULL;
    LosTaskCB *taskCB = NULL;
    UINT32 errRet = OS_ERROR;
    VOID *pool = (VOID *)m_aucSysMem1;
    VOID *poolTmp = NULL;
    UINT32 poolSize = OS_SYS_MEM_SIZE;
#ifdef LOSCFG_TASK_STACK_PROTECT
    AARCHPTR MMUProtectAddr;
    UINT32 alignStackSize;
    MMU_PARAM mPara;
#endif

    if (taskID == NULL) {
        return LOS_ERRNO_TSK_ID_INVALID;
    }

    if (initParam == NULL) {
        return LOS_ERRNO_TSK_PTR_NULL;
    }

    if (initParam->pcName == NULL) {
        return LOS_ERRNO_TSK_NAME_EMPTY;
    }

    if (initParam->pfnTaskEntry == NULL) {
        return LOS_ERRNO_TSK_ENTRY_NULL;
    }

    if ((initParam->usTaskPrio) > OS_TASK_PRIORITY_LOWEST) {
        return LOS_ERRNO_TSK_PRIOR_ERROR;
    }
#ifdef LOSCFG_EXC_INTERACTION
    if (!osExcInteractionTaskCheck(initParam)) {
        pool = m_aucSysMem0;
        poolSize = OS_EXC_INTERACTMEM_SIZE;
    }
#endif
#ifdef LOSCFG_TASK_STACK_PROTECT
    if (initParam->uwStackSize > ((poolSize > (2 * MMU_4K)) ? poolSize - 2 * MMU_4K : 0)) {
#else
    if (initParam->uwStackSize > poolSize) {
#endif
        return LOS_ERRNO_TSK_STKSZ_TOO_LARGE;
    }

    if (initParam->uwStackSize == 0) {
        initParam->uwStackSize = LOSCFG_BASE_CORE_TSK_DEFAULT_STACK_SIZE;
    }
    initParam->uwStackSize = ALIGN(initParam->uwStackSize, LOSCFG_STACK_POINT_ALIGN_SIZE);

    if (initParam->uwStackSize < LOS_TASK_MIN_STACK_SIZE) {
        return LOS_ERRNO_TSK_STKSZ_TOO_SMALL;
    }

    intSave = LOS_IntLock();
    while (!LOS_ListEmpty(&g_taskRecyleList)) {
        poolTmp = (VOID *)m_aucSysMem1;
        taskCB = OS_TCB_FROM_PENDLIST(LOS_DL_LIST_FIRST(&g_taskRecyleList)); /*lint !e413*/
        LOS_ListDelete(LOS_DL_LIST_FIRST(&g_taskRecyleList));
        LOS_ListAdd(&g_losFreeTask, &taskCB->pendList);
#ifdef LOSCFG_TASK_STACK_PROTECT
        MMUProtectAddr = taskCB->topOfStack - MMU_4K;
        mPara.startAddr = MMUProtectAddr;
        mPara.endAddr = MMUProtectAddr + MMU_4K;
        mPara.uwFlag = BUFFER_ENABLE | CACHE_ENABLE | ACCESS_PERM_RW_RW;
        mPara.stPage = (SENCOND_PAGE *)&stAppPage;
        LOS_MMUParamSet(&mPara);
#ifdef LOSCFG_EXC_INTERACTION
        if (MMUProtectAddr < (AARCHPTR)m_aucSysMem1) {
            poolTmp = (VOID *)m_aucSysMem0;
        }
#endif
        (VOID)LOS_MemFree(poolTmp, (VOID *)MMUProtectAddr);
#else
#ifdef LOSCFG_EXC_INTERACTION
        if (taskCB->topOfStack < (AARCHPTR)m_aucSysMem1) {
            poolTmp = (VOID *)m_aucSysMem0;
        }
#endif
        (VOID)LOS_MemFree(poolTmp, (VOID *)taskCB->topOfStack);
#endif
        taskCB->topOfStack = (AARCHPTR)NULL;
    }

    if (LOS_ListEmpty(&g_losFreeTask)) {
        errRet = LOS_ERRNO_TSK_TCB_UNAVAILABLE;
        OS_GOTO_ERREND();
    }

    taskCB = OS_TCB_FROM_PENDLIST(LOS_DL_LIST_FIRST(&g_losFreeTask)); /*lint !e413*/
    LOS_ListDelete(LOS_DL_LIST_FIRST(&g_losFreeTask));
    (VOID)LOS_IntRestore(intSave);
    tempTaskID = taskCB->taskID;

#ifdef LOSCFG_TASK_STACK_PROTECT
    alignStackSize = ALIGN(initParam->stackSize, MMU_4K);
    MMUProtectAddr = (AARCHPTR)LOS_MemAllocAlign(pool, (alignStackSize + MMU_4K), MMU_4K);
    if (MMUProtectAddr == 0) {
        topStack = (VOID *)NULL;
    } else {
        topStack = (VOID *)(MMUProtectAddr + MMU_4K);
        mPara.startAddr = MMUProtectAddr;
        mPara.endAddr = MMUProtectAddr + MMU_4K;
        mPara.uwFlag = BUFFER_ENABLE | CACHE_ENABLE | ACCESS_PERM_RO_RO;
        mPara.stPage = (SENCOND_PAGE *)&stAppPage;
        LOS_MMUParamSet(&mPara);
    }
#else
    topStack = (void *)LOS_MemAllocAlign(pool, initParam->uwStackSize, LOSCFG_STACK_POINT_ALIGN_SIZE);
#endif

    if (topStack == NULL) {
        intSave = LOS_IntLock();
        LOS_ListAdd(&g_losFreeTask, &taskCB->pendList);
        errRet = LOS_ERRNO_TSK_NO_MEMORY;
        OS_GOTO_ERREND();
    }

    stackPtr = OsTskStackInit(tempTaskID, initParam->uwStackSize, topStack);
    taskCB->stackPointer = stackPtr;
    taskCB->args[0] = initParam->auwArgs[0];
    taskCB->args[1] = initParam->auwArgs[1];
    taskCB->args[2] = initParam->auwArgs[2];
    taskCB->args[3] = initParam->auwArgs[3];
    taskCB->topOfStack = (AARCHPTR)topStack;
    taskCB->stackSize = initParam->uwStackSize;
    taskCB->taskSem = NULL;
    taskCB->threadJoin = NULL;
    taskCB->taskMux = NULL;
    taskCB->taskStatus = OS_TASK_STATUS_SUSPEND;
    /* set the task is detached or joinable */
    taskCB->taskStatus |= (initParam->uwResved ? LOS_TASK_STATUS_DETACHED : 0);
    taskCB->priority = initParam->usTaskPrio;
    taskCB->priBitMap = 0;
    taskCB->taskEntry = initParam->pfnTaskEntry;
    taskCB->event.uwEventID = 0xFFFFFFFF;
    taskCB->eventMask = 0;
    taskCB->taskName = initParam->pcName;
    taskCB->msg = NULL;
    if (osConsoleIDSetHook != NULL) { /*lint !e506*/
        osConsoleIDSetHook(taskCB->taskID, g_losTask.runTask->taskID);
    }
    *taskID = tempTaskID;
    return LOS_OK;

LOS_ERREND:
    (VOID)LOS_IntRestore(intSave);
    return errRet;
}

/*****************************************************************************
 Function : LOS_TaskCreate
 Description : Create a task
 Input       : initParam --- Task init parameters
 Output      : taskID    --- Save task ID
 Return      : LOS_OK on success or error code on failure
 *****************************************************************************/
LITE_OS_SEC_TEXT_INIT UINT32 LOS_TaskCreate(UINT32 *taskID, TSK_INIT_PARAM_S *initParam)
{
    UINT32 ret;
    UINTPTR intSave;
    LosTaskCB *taskCB = NULL;

    ret = LOS_TaskCreateOnly(taskID, initParam);
    if (ret != LOS_OK) {
        return ret;
    }
    taskCB = OS_TCB_FROM_TID(*taskID);

    intSave = LOS_IntLock();
    taskCB->taskStatus &= (~OS_TASK_STATUS_SUSPEND);
    taskCB->taskStatus |= OS_TASK_STATUS_READY;

#ifdef LOSCFG_KERNEL_CPUP
    g_cpup[taskCB->taskID].taskID = taskCB->taskID;
    g_cpup[taskCB->taskID].status = taskCB->taskStatus;
#endif

    OsPriqueueEnqueue(&taskCB->pendList, taskCB->priority);
    g_losTask.newTask = LOS_DL_LIST_ENTRY(OsPriqueueTop(), LosTaskCB, pendList); /*lint !e413*/

    if ((g_taskScheduled) && (g_losTaskLock == 0)) {
        if (g_losTask.runTask != g_losTask.newTask) {
            if (LOS_CHECK_SCHEDULE) {
                (VOID)LOS_IntRestore(intSave);
                OsSchedule();
                return LOS_OK;
            }
        }
    }

    (VOID)LOS_IntRestore(intSave);
    return LOS_OK;
}

/*****************************************************************************
 Function : LOS_TaskResume
 Description : Resume suspend task
 Input       : taskID --- Task ID
 Output      : None
 Return      : LOS_OK on success or error code on failure
 *****************************************************************************/
LITE_OS_SEC_TEXT_INIT UINT32 LOS_TaskResume(UINT32 taskID)
{
    UINTPTR intSave;
    LosTaskCB *taskCB = NULL;
    UINT16 tempStatus;
    UINT32 errRet = OS_ERROR;

    if (taskID >= g_taskMaxNum) {
        return LOS_ERRNO_TSK_ID_INVALID;
    }

    taskCB = OS_TCB_FROM_TID(taskID);
    intSave = LOS_IntLock();
    tempStatus = taskCB->taskStatus;

    if (OS_TASK_STATUS_UNUSED & tempStatus) {
        errRet = LOS_ERRNO_TSK_NOT_CREATED;
        OS_GOTO_ERREND();
    } else if (!(OS_TASK_STATUS_SUSPEND & tempStatus)) {
        errRet = LOS_ERRNO_TSK_NOT_SUSPENDED;
        OS_GOTO_ERREND();
    }

    taskCB->taskStatus &= (~OS_TASK_STATUS_SUSPEND);
    if (!(OS_CHECK_TASK_BLOCK & taskCB->taskStatus)) {
        taskCB->taskStatus |= OS_TASK_STATUS_READY;
        OsPriqueueEnqueue(&taskCB->pendList, taskCB->priority);
        if (g_taskScheduled) {
            (VOID)LOS_IntRestore(intSave);
            LOS_Schedule();
            return LOS_OK;
        }
        g_losTask.newTask = LOS_DL_LIST_ENTRY(OsPriqueueTop(), LosTaskCB, pendList); /*lint !e413*/
    }

    (VOID)LOS_IntRestore(intSave);
    return LOS_OK;

LOS_ERREND:
    (VOID)LOS_IntRestore(intSave);
    return errRet;
}

/*****************************************************************************
 Function : LOS_TaskSuspend
 Description : Suspend task
 Input       : taskID --- Task ID
 Output      : None
 Return      : LOS_OK on success or error code on failure
 *****************************************************************************/
LITE_OS_SEC_TEXT_INIT UINT32 LOS_TaskSuspend(UINT32 taskID)
{
    UINTPTR intSave;
    LosTaskCB *taskCB = NULL;
    UINT16 tempStatus;
    UINT32 errRet = OS_ERROR;

    if (taskID == g_idleTaskID) {
        return LOS_ERRNO_TSK_OPERATE_IDLE;
    }

    if (taskID == g_swtmrTaskID) {
        return LOS_ERRNO_TSK_SUSPEND_SWTMR_NOT_ALLOWED;
    }

    if (OS_TSK_GET_INDEX(taskID) >= g_taskMaxNum) {
        return LOS_ERRNO_TSK_ID_INVALID;
    }

    taskCB = OS_TCB_FROM_TID(taskID);
    intSave = LOS_IntLock();
    tempStatus = taskCB->taskStatus;
    if (OS_TASK_STATUS_UNUSED & tempStatus) {
        errRet = LOS_ERRNO_TSK_NOT_CREATED;
        OS_GOTO_ERREND();
    }

    if (OS_TASK_STATUS_SUSPEND & tempStatus) {
        errRet = LOS_ERRNO_TSK_ALREADY_SUSPENDED;
        OS_GOTO_ERREND();
    }

    if ((OS_TASK_STATUS_RUNNING & tempStatus) && (g_losTaskLock != 0)) {
        errRet = LOS_ERRNO_TSK_SUSPEND_LOCKED;
        OS_GOTO_ERREND();
    }

    if (OS_TASK_STATUS_READY & tempStatus) {
        OsPriqueueDequeue(&taskCB->pendList);
        taskCB->taskStatus &= (~OS_TASK_STATUS_READY);
    }

    taskCB->taskStatus |= OS_TASK_STATUS_SUSPEND;
    if (taskID == g_losTask.runTask->taskID) {
        (VOID)LOS_IntRestore(intSave);
        LOS_Schedule();
        return LOS_OK;
    }

    (VOID)LOS_IntRestore(intSave);
    return LOS_OK;

LOS_ERREND:
    (VOID)LOS_IntRestore(intSave);
    return errRet;
}

/*****************************************************************************
 Function : LOS_TaskDelete
 Description : Delete a task
 Input       : taskID --- Task ID
 Output      : None
 Return      : LOS_OK on success or error code on failure
 *****************************************************************************/
LITE_OS_SEC_TEXT_INIT UINT32 LOS_TaskDelete(UINT32 taskID)
{
    UINTPTR intSave;
    LosTaskCB *taskCB = NULL;
    UINT16 tempStatus;
    UINT32 errRet = OS_ERROR;
    VOID *pool = (VOID *)m_aucSysMem1;
#ifdef LOSCFG_TASK_STACK_PROTECT
    AARCHPTR mMUProtectAddr;
    MMU_PARAM mPara;
#endif

    if (taskID == g_idleTaskID) {
        return LOS_ERRNO_TSK_OPERATE_IDLE;
    }
#ifndef LOSCFG_EXC_INTERACTION
    if (taskID == g_swtmrTaskID) {
        return LOS_ERRNO_TSK_SUSPEND_SWTMR_NOT_ALLOWED;
    }
#endif
    if (OS_TSK_GET_INDEX(taskID) >= g_taskMaxNum) {
        return LOS_ERRNO_TSK_ID_INVALID;
    }

    intSave = LOS_IntLock();

    taskCB = OS_TCB_FROM_TID(taskID);

    tempStatus = taskCB->taskStatus;

    if (OS_TASK_STATUS_UNUSED & tempStatus) {
        errRet = LOS_ERRNO_TSK_NOT_CREATED;
        OS_GOTO_ERREND();
    }

    /* If the task is running and scheduler is locked then you can not delete it */
    if ((OS_TASK_STATUS_RUNNING & tempStatus) && (g_losTaskLock != 0)) {
        errRet = LOS_ERRNO_TSK_DELETE_LOCKED;
        OS_GOTO_ERREND();
    }

    if (OS_TASK_STATUS_READY & tempStatus) {
        OsPriqueueDequeue(&taskCB->pendList);
        taskCB->taskStatus &= (~OS_TASK_STATUS_READY);
    } else if ((OS_TASK_STATUS_PEND & tempStatus) || (OS_TASK_STATUS_PEND_QUEUE & tempStatus)) {
        LOS_ListDelete(&taskCB->pendList);
    }

    if ((OS_TASK_STATUS_DELAY | OS_TASK_STATUS_PEND_TIME) & tempStatus) {
        OsTimerListDelete(taskCB);
    }

    taskCB->taskStatus &= (~(OS_TASK_STATUS_SUSPEND));
    taskCB->taskStatus |= OS_TASK_STATUS_UNUSED;
    taskCB->event.uwEventID = 0xFFFFFFFF;
    taskCB->eventMask = 0;
#ifdef LOSCFG_KERNEL_CPUP
    (VOID)memset_s((VOID *)&g_cpup[taskCB->taskID], sizeof(OsCpupCB), 0, sizeof(OsCpupCB));
#endif
#ifdef OS_MEM_ENABLE_MEM_STATISTICS
    OS_MEM_CLEAR(taskID);
#endif
    g_losTask.newTask = LOS_DL_LIST_ENTRY(OsPriqueueTop(), LosTaskCB, pendList); /*lint !e413*/
    if (OS_TASK_STATUS_RUNNING & taskCB->taskStatus) {
        LOS_ListTailInsert(&g_taskRecyleList, &taskCB->pendList);
        g_losTask.runTask = &g_taskCBArray[g_taskMaxNum];
        g_losTask.runTask->taskID = taskID;
        g_losTask.runTask->taskStatus = taskCB->taskStatus;
        g_losTask.runTask->topOfStack = taskCB->topOfStack;
        g_losTask.runTask->taskName = taskCB->taskName;
        taskCB->taskStatus = OS_TASK_STATUS_UNUSED;
        (VOID)LOS_IntRestore(intSave);
        OsSchedule();
        return LOS_OK;
    } else {
        taskCB->taskStatus = OS_TASK_STATUS_UNUSED;
        LOS_ListAdd(&g_losFreeTask, &taskCB->pendList);
#ifdef LOSCFG_TASK_STACK_PROTECT
        mMUProtectAddr = taskCB->topOfStack - MMU_4K;
        mPara.startAddr = mMUProtectAddr;
        mPara.endAddr = mMUProtectAddr + MMU_4K;
        mPara.uwFlag = BUFFER_ENABLE | CACHE_ENABLE | ACCESS_PERM_RW_RW;
        mPara.stPage = (SENCOND_PAGE *)&stAppPage;
        LOS_MMUParamSet(&mPara);
#ifdef LOSCFG_EXC_INTERACTION
        if (mMUProtectAddr < (AARCHPTR)m_aucSysMem1) {
            pool = (VOID *)m_aucSysMem0;
        }
#endif
        (VOID)LOS_MemFree(pool, (VOID *)mMUProtectAddr);
#else
#ifdef LOSCFG_EXC_INTERACTION
        if (taskCB->topOfStack < (AARCHPTR)m_aucSysMem1) {
            pool = (VOID *)m_aucSysMem0;
        }
#endif
        (VOID)LOS_MemFree(pool, (VOID *)taskCB->topOfStack);
#endif
        taskCB->topOfStack = (AARCHPTR)NULL;
    }

    (VOID)LOS_IntRestore(intSave);
    return LOS_OK;

LOS_ERREND:
    (VOID)LOS_IntRestore(intSave);
    return errRet;
}

/*****************************************************************************
 Function : LOS_TaskDelay
 Description : delay the current task
 Input       : tick    --- time
 Output      :None
 Return      : LOS_OK on success or error code on failure
 *****************************************************************************/
LITE_OS_SEC_TEXT UINT32 LOS_TaskDelay(UINT32 tick)
{
    UINTPTR intSave;

    if (OS_INT_ACTIVE) {
        PRINT_ERR("!!!LOS_ERRNO_TSK_DELAY_IN_INT!!!\n");
        return LOS_ERRNO_TSK_DELAY_IN_INT;
    }

#if (LOSCFG_BASE_CORE_SWTMR == YES)
    /* DO NOT Call blocking API in software timer task */
    if (g_losTask.runTask->taskEntry == (TSK_ENTRY_FUNC)OsSwtmrTask) {
        PRINTK("Warning: DO NOT call %s in software timer callback.\n", __FUNCTION__);
        osBackTrace();
    }
#endif

    if (g_losTaskLock != 0) {
        return LOS_ERRNO_TSK_DELAY_IN_LOCK;
    }

    if (tick == 0) {
        return LOS_TaskYield();
    } else {
        intSave = LOS_IntLock();
        OsPriqueueDequeue(&(g_losTask.runTask->pendList));
        g_losTask.runTask->taskStatus &= (~OS_TASK_STATUS_READY);
        OsTaskAdd2TimerList((LosTaskCB *)g_losTask.runTask, tick);
        g_losTask.runTask->taskStatus |= OS_TASK_STATUS_DELAY;
        (VOID)LOS_IntRestore(intSave);
        LOS_Schedule();
    }

    return LOS_OK;
}

/*****************************************************************************
 Function : LOS_TaskPriGet
 Description : Get the priority of the task
 Input       : taskID --- The task id value is obtained from task creation.
 Output      : None
 Return      : TSK_PRIOR_T on success or OS_INVALID on failure
 *****************************************************************************/
LITE_OS_SEC_TEXT_MINOR UINT16 LOS_TaskPriGet(UINT32 taskID)
{
    UINTPTR intSave;
    LosTaskCB *taskCB = NULL;
    UINT16 priority;

    if (OS_CHECK_TSK_PID_NOIDLE(taskID)) {
        return (UINT16)OS_INVALID;
    }

    taskCB = OS_TCB_FROM_TID(taskID);

    intSave = LOS_IntLock();

    if (OS_TASK_STATUS_UNUSED & taskCB->taskStatus) {
        (VOID)LOS_IntRestore(intSave);
        return (UINT16)OS_INVALID;
    }

    priority = taskCB->priority;
    (VOID)LOS_IntRestore(intSave);
    return priority;
}

/*****************************************************************************
 Function : LOS_TaskPriSet
 Description : Set the priority of the task
 Input       : taskID --- The task id value is obtained from task creation.
               taskPrio --- Task priority
 Output      : None
 Return      : None
 *****************************************************************************/
LITE_OS_SEC_TEXT_MINOR UINT32 LOS_TaskPriSet(UINT32 taskID, UINT16 taskPrio)
{
    BOOL isReady;
    UINTPTR intSave;
    LosTaskCB *taskCB = NULL;
    UINT16 tempStatus;

    if (taskPrio > OS_TASK_PRIORITY_LOWEST) {
        return LOS_ERRNO_TSK_PRIOR_ERROR;
    }

    if (taskID == g_idleTaskID) {
        return LOS_ERRNO_TSK_OPERATE_IDLE;
    }

    if (OS_CHECK_TSK_PID_NOIDLE(taskID)) {
        return LOS_ERRNO_TSK_ID_INVALID;
    }

    taskCB = OS_TCB_FROM_TID(taskID);
    intSave = LOS_IntLock();
    tempStatus = taskCB->taskStatus;
    if (OS_TASK_STATUS_UNUSED & tempStatus) {
        (VOID)LOS_IntRestore(intSave);
        return LOS_ERRNO_TSK_NOT_CREATED;
    }
    /* delete the task and insert with right priority into ready queue */
    isReady = (OS_TASK_STATUS_READY & tempStatus);
    if (isReady) {
        OsPriqueueDequeue(&taskCB->pendList);
        taskCB->priority = taskPrio;
        OsPriqueueEnqueue(&taskCB->pendList, taskCB->priority);
    } else {
        taskCB->priority = taskPrio;
    }
    (VOID)LOS_IntRestore(intSave);
    /* delete the task and insert with right priority into ready queue */
    if (isReady) {
        LOS_Schedule();
    }
    return LOS_OK;
}

/*****************************************************************************
 Function : LOS_CurTaskPriSet
 Description : Set the priority of the current task
 Input       : taskPrio --- Task priority
 Output      : None
 Return      : None
 *****************************************************************************/
LITE_OS_SEC_TEXT_MINOR UINT32 LOS_CurTaskPriSet(UINT16 taskPrio)
{
    UINT32 ret;
    ret = LOS_TaskPriSet(g_losTask.runTask->taskID, taskPrio);
    return ret;
}

/**************************************************************************
 Function    : OsTaskWait
 Description : pend a task in list
 Input       : list --- wait task list
                : taskStatus --- task status
                : timeOut -- Expiry time
 Output      : none
 Return      : LOS_OK on success or LOS_NOK on failure
**************************************************************************/
VOID OsTaskWait(LOS_DL_LIST *list, UINT32 taskStatus, UINT32 timeout)
{
    LosTaskCB *runTsk = NULL;
    LOS_DL_LIST *pendObj = NULL;

    runTsk = g_losTask.runTask;
    OsPriqueueDequeue(&runTsk->pendList);
    runTsk->taskStatus &= (~OS_TASK_STATUS_READY);
    pendObj = &runTsk->pendList;
    runTsk->taskStatus |= taskStatus;
    LOS_ListTailInsert(list, pendObj);
    if (timeout != LOS_WAIT_FOREVER) {
        runTsk->taskStatus |= OS_TASK_STATUS_PEND_TIME;
        OsTaskAdd2TimerList((LosTaskCB *)runTsk, timeout);
    }
}

/**************************************************************************
 Function    : OsTaskWake
 Description : delete the task from pendlist and also add to the priqueue
 Input       : resumedTask --> resumed task
 Output      : resumedTask
 Return      : none
**************************************************************************/
VOID OsTaskWake(LosTaskCB *resumedTask, UINT32 taskStatus)
{
    LOS_ListDelete(&resumedTask->pendList);
    resumedTask->taskStatus &= (~taskStatus);

    if (resumedTask->taskStatus & OS_TASK_STATUS_PEND_TIME) {
        OsTimerListDelete(resumedTask);
        resumedTask->taskStatus &= (~OS_TASK_STATUS_PEND_TIME);
    }
    if (!(resumedTask->taskStatus & OS_TASK_STATUS_SUSPEND)) {
        resumedTask->taskStatus |= OS_TASK_STATUS_READY;
        OsPriqueueEnqueue(&resumedTask->pendList, resumedTask->priority);
    }
}

/*****************************************************************************
 Function : LOS_TaskYield
 Description : Adjust the procedure order of specified task
 Input       : taskPrio
               nextTask
 Output      : None
 Return      : LOS_OK on success or error code on failure
 *****************************************************************************/
LITE_OS_SEC_TEXT_MINOR UINT32 LOS_TaskYield(VOID)
{
    UINT32 tskCount ;
    UINTPTR intSave;

    if (g_losTask.runTask->taskID >= g_taskMaxNum) {
        return LOS_ERRNO_TSK_ID_INVALID;
    }
    if (!(g_losTask.runTask->taskStatus & OS_TASK_STATUS_READY)) {
        return LOS_OK;
    }
    intSave = LOS_IntLock();
    tskCount = OsPriqueueSize(g_losTask.runTask->priority);
    if (tskCount > 1) {
        LOS_ListDelete(&(g_losTask.runTask->pendList));
        g_losTask.runTask->taskStatus |= OS_TASK_STATUS_READY;
        OsPriqueueEnqueue(&(g_losTask.runTask->pendList), g_losTask.runTask->priority);
    } else {
        (VOID)LOS_IntRestore(intSave);
        return LOS_ERRNO_TSK_YIELD_NOT_ENOUGH_TASK;
    }
    (VOID)LOS_IntRestore(intSave);
    LOS_Schedule();
    return LOS_OK;
}

/*****************************************************************************
 Function : LOS_TaskLock
 Description : Task lock
 Input       : None
 Output      : None
 Return      : None
 *****************************************************************************/
LITE_OS_SEC_TEXT_MINOR VOID LOS_TaskLock(VOID)
{
    UINTPTR intSave;

    intSave = LOS_IntLock();
    g_losTaskLock++;
    (VOID)LOS_IntRestore(intSave);
}

/*****************************************************************************
 Function : LOS_TaskUnlock
 Description : Task unlock
 Input       : None
 Output      : None
 Return      : None
 *****************************************************************************/
LITE_OS_SEC_TEXT_MINOR VOID LOS_TaskUnlock(VOID)
{
    UINTPTR intSave;

    intSave = LOS_IntLock();
    if (g_losTaskLock > 0) {
        g_losTaskLock--;
        if (g_losTaskLock == 0) {
            (VOID)LOS_IntRestore(intSave);
            LOS_Schedule();
            return;
        }
    }

    (VOID)LOS_IntRestore(intSave);
}

/*****************************************************************************
 Function : LOS_TaskInfoGet
 Description : Get the information of the task
 Input       : taskID  --- the task id which created by LOS_TaskCreate
 Output      : taskInfo --- task information
 Return      : LOS_OK on success or error code on failure
 *****************************************************************************/
LITE_OS_SEC_TEXT_MINOR UINT32 LOS_TaskInfoGet(UINT32 taskID, TSK_INFO_S *taskInfo)
{
    UINT32 intSave;
    LosTaskCB *taskCB = NULL;
    AARCHPTR *stack = NULL;

    if (taskInfo == NULL) {
        return LOS_ERRNO_TSK_PTR_NULL;
    }

    if (OS_CHECK_TSK_PID_NOIDLE(taskID)) {
        return LOS_ERRNO_TSK_ID_INVALID;
    }

    taskCB = OS_TCB_FROM_TID(taskID);
    intSave = LOS_IntLock();

    if (OS_TASK_STATUS_UNUSED & taskCB->taskStatus) {
        (VOID)LOS_IntRestore(intSave);
        return LOS_ERRNO_TSK_NOT_CREATED;
    }

    if (!(OS_TASK_STATUS_RUNNING & taskCB->taskStatus) || (OS_INT_ACTIVE)) {
        taskInfo->uwSP = (AARCHPTR)taskCB->stackPointer;
    } else {
        __asm__ __volatile__("mov %0, sp"
                             : "=r"(taskInfo->uwSP));
    }

    taskInfo->usTaskStatus = taskCB->taskStatus;
    taskInfo->usTaskPrio = taskCB->priority;
    taskInfo->uwStackSize = taskCB->stackSize;
    taskInfo->uwTopOfStack = taskCB->topOfStack;
    taskInfo->uwEvent = taskCB->event;
    taskInfo->uwEventMask = taskCB->eventMask;
    taskInfo->pTaskSem = taskCB->taskSem;
    taskInfo->pTaskMux = taskCB->taskMux;
    taskInfo->uwTaskID = taskID;

    if (strncpy_s(taskInfo->acName, LOS_TASK_NAMELEN, taskCB->taskName, (LOS_TASK_NAMELEN - 1))) {
        PRINT_ERR("Task name copy failed!\n");
    }
    taskInfo->acName[LOS_TASK_NAMELEN - 1] = '\0';

    taskInfo->uwBottomOfStack = TRUNCATE(((AARCHPTR)(taskCB->topOfStack) + (taskCB->stackSize)),
        OS_TASK_STACK_ADDR_ALIGN);
    taskInfo->uwCurrUsed = taskInfo->uwBottomOfStack - taskInfo->uwSP;

    if (*(AARCHPTR *)taskInfo->uwTopOfStack == OS_TASK_MAGIC_WORD) {
        stack = (AARCHPTR *)(taskInfo->uwTopOfStack + sizeof(AARCHPTR));
        while ((stack < (AARCHPTR *)taskInfo->uwSP) && (*stack == OS_TASK_STACK_INIT)) {
            stack += 1;
        }

        taskInfo->uwPeakUsed = taskCB->stackSize - ((AARCHPTR)stack - taskInfo->uwTopOfStack);
        taskInfo->bOvf = FALSE;
    } else {
        taskInfo->uwPeakUsed = 0xFFFFFFFF;
        taskInfo->bOvf = TRUE;
    }

    (VOID)LOS_IntRestore(intSave);

    return LOS_OK;
}

#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */
